package com.cnjson.sensor.protocolARP.waterQualitySensorProtocol;


import com.cnjson.sensor.db.dao.EquipmeStateDao;
import com.cnjson.sensor.db.entity.EquipmentState;
import com.cnjson.sensor.protocolARP.GeneralProtocolAbstract;
import com.cnjson.sensor.protocolARP.waterQualitySensorProtocol.controlEquipmentResponse.RunEquipmentResponse;
import com.cnjson.sensor.protocolARP.waterQualitySensorProtocol.controlEquipmentResponse.ShutdownEquipmentResponse;
import com.cnjson.sensor.protocolARP.waterQualitySensorProtocol.dataReport.DataReport;
import com.cnjson.sensor.protocolARP.waterQualitySensorProtocol.keepAlive.KeepAlive;
import com.cnjson.sensor.protocolARP.waterQualitySensorProtocol.loader.Load;
import com.cnjson.sensor.util.DataFormater;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.*;

@Component
public class WaterQualitySensorProtocol extends GeneralProtocolAbstract {
    private static final Logger logger = LoggerFactory.getLogger(WaterQualitySensorProtocol.class);

    @Autowired
    private EquipmeStateDao equipmeStateDao;


    private Load load;
    private KeepAlive keepAlive;
    private DataReport dataReport;
    private RunEquipmentResponse runEquipment;
    private ShutdownEquipmentResponse shutdownEquipment;


    Map<String, WaterQualitySensorResolveInterface> resolveInterfaceMap = new HashMap<>();

    public WaterQualitySensorProtocol(Load load, KeepAlive keepAlive, DataReport dataReport,
                                      RunEquipmentResponse runEquipment, ShutdownEquipmentResponse shutdownEquipment) {

        resolveInterfaceMap.put("0x41", load);
        resolveInterfaceMap.put("0x43", keepAlive);
        resolveInterfaceMap.put("0x47", dataReport);
        resolveInterfaceMap.put("0x02", runEquipment);
        resolveInterfaceMap.put("0x82", shutdownEquipment);

//        0x29 报警
//        0x30 索要数据
//        0x31 状态数据上报
//        0x32 警情上报

    }


    @Override
    public String[] checkData(SocketChannel client) {
        try {

            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            int readBytes = client.read(readBuffer);
            if (readBytes > 0) {
                //反转缓冲区（复位）
                readBuffer.flip();
                byte[] dataBytes = new byte[readBuffer.remaining()];
                //接受缓冲区数据
                readBuffer.get(dataBytes);


                int bytelen=dataBytes.length;
                ByteBuffer crcCheckData = ByteBuffer.allocate(bytelen - 3-4);
                String[] dataString=new String[bytelen];
                for (int j = 0; j <bytelen; j++) {
                    byte b = dataBytes[j];
                    dataString[j]=DataFormater.byteToHex(b);

                    if (j>=3&&j < bytelen - 4) { //crc校验数据  从第4位(包括长度)开始到倒数第4位
                        crcCheckData.put(b);
                    }
                }

                StringBuilder dataStringBuilder=new StringBuilder(bytelen);
                dataStringBuilder.append(dataString[0]);
                for (int j=0;j<bytelen-1;j++)
                    dataStringBuilder.append(" "+dataString[j+1]);

                logger.info("接收到的数据为 : " + dataStringBuilder);
                //crc验证数据是否正确



                boolean isCorrect = checkCRCVal(crcCheckData,dataString);
                //测试数据
                if (!isCorrect) {
                    logger.warn("CRC验证不通过!");
                    return null;
                }


                return dataString;
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("读取数据出错");
        }
        return null;
    }

    @Override
    public byte[] handleData(SocketChannel client, String[] data) {
        byte[] response;

        // 帧代号1
        int flag = Integer.valueOf(data[4]);

        //根据不同的flag，进行相应的解析
        response = resolveInterfaceMap.get(flag + "").resolve(data, client);
        return response;
    }


    @Override
    public void doSomethingInReadingError(SocketChannel client) {
        try {
            String address = client.getRemoteAddress().toString();

            EquipmentState equipmentState = new EquipmentState();
            equipmentState.setRunningState("0");  //关闭状态
            equipmentState.setRemoteAddress(address);
            equipmeStateDao.save(equipmentState);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("nio client 读取远程设备发送ip错误");
        }
    }


    /**
     * 获取设备在址
     *
     * @param data 去掉包头（不包含前四位）的数据包
     * @return 返回设备地址4位byte
     */
    public static byte[] getDevice(ByteBuffer data) {
        byte[] device = new byte[4];
        System.arraycopy(data.array(), 3, device, 0, 4);
        return device;
    }

    /**
     * 获取设备在址
     *
     * @param data 去掉包头（不包含前四位）的数据包
     * @return 返回设备地址2位byte
     */
    public static byte[] getRelDevice(ByteBuffer data) {
        byte[] device = new byte[2];
        System.arraycopy(data.array(), 3, device, 0, 2);
        return device;
    }


}
